package com.cuitrip.util;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.text.TextUtils;

import com.cuitrip.app.MainApplication;
import com.cuitrip.service.R;
import com.cuitrip.task.DialogAsyncTask;
import com.lab.app.BaseActivity;
import com.lab.logtrack.AppLog;
import com.lab.utils.DictionaryUtil;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by ak
 */
public class ImageFetcherManager {

    private static final String TAG = "ImageFetcherManager";

    public static final int IMAGE_MAX_SIZE_LIMIT = 2 * 1000 * 1000;

    private static final int OPEN_MODE_ACTIVITY = 1;
    private static final int OPEN_MODE_FRAGMENT = 2;

    private static final int BITMAP_SIZE_LEVEL_480P = 720 * 480;
    private static final int BITMAP_SIZE_LEVEL_720P = 1280 * 720;
    private static final int BITMAP_SIZE_LEVEL_1280P = 1920 * 1080;
    private static final int BITMAP_SIZE_LEVEL_LARGE = 3000 * 2000;

    public final static int REQUEST_CODE_PICK_IMAGE = 1001;
    public final static int REQUEST_CODE_TAKE_CAMERA = 1002;
    public final static int REQUEST_CODE_CROP_IMAGE = 1003;

    private File mPickImageFile;
    private File mTakeCameraFile;
    private File mCropImageFile;
    private File mCompressImageFile;

    private BaseActivity mActivity;
    private Fragment mFragment;
    private Source mSource;
    private int mOpenMode;

    public static ImageFetcherManager newInstance(BaseActivity activity) {
        return new ImageFetcherManager(activity, null);
    }

    public static ImageFetcherManager newInstance(BaseActivity activity, Source source) {
        return new ImageFetcherManager(activity, source);
    }

    public static ImageFetcherManager newInstance(Fragment fragment) {
        return new ImageFetcherManager(fragment, null);
    }

    public static ImageFetcherManager newInstance(Fragment fragment, Source source) {
        return new ImageFetcherManager(fragment, source);
    }

    public ImageFetcherManager(BaseActivity activity, Source source) {
        mActivity = activity;
        mSource = source;
        mOpenMode = OPEN_MODE_ACTIVITY;
    }

    public ImageFetcherManager(Fragment fragment, Source source) {
        mFragment = fragment;
        mSource = source;
        if (null != fragment) {
            try {
                mActivity = (BaseActivity) fragment.getActivity();
            } catch (Exception e) {
            }
        }
        mOpenMode = OPEN_MODE_FRAGMENT;
    }

    public boolean cropImage(File originFile, File targetFile, CropImageParam param) {
        mCropImageFile = null;
        if (!checkEnvironment() || null == originFile || !originFile.isFile() || TextUtils.isEmpty(originFile.getAbsolutePath()))
            return false;
        mCropImageFile = targetFile;
        if (null == mCropImageFile)
            return false;
        // 计算裁剪参数值
        int aspectX = 1;
        int aspectY = 1;
        int outputX = 800;
        int outputY = 800;
        if (null != param) {
            if (param.mAspectX > 0 && param.mAspectY > 0) {
                aspectX = param.mAspectX;
                aspectY = param.mAspectY;
            }
            if (param.mOutputX > 0 && param.mOutputY > 0) {
                outputX = param.mOutputX;
                outputY = param.mOutputY;
            }
        }
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(Uri.fromFile(originFile), "image/*");
        intent.putExtra("crop", "true");
        intent.putExtra("aspectX", aspectX);
        intent.putExtra("aspectY", aspectY);
        intent.putExtra("outputX", outputX);
        intent.putExtra("outputY", outputY);
        intent.putExtra("return-data", false);
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        intent.putExtra("noFaceDetection", true);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mCropImageFile));
        if (mOpenMode == OPEN_MODE_ACTIVITY) {
            mActivity.startActivityForResult(intent, REQUEST_CODE_CROP_IMAGE);
        } else if (mOpenMode == OPEN_MODE_FRAGMENT) {
            mFragment.startActivityForResult(intent, REQUEST_CODE_CROP_IMAGE);
        }
        return true;
    }

    public File getPickImageFile(Uri uri) {
        mPickImageFile = null;
        String imagePath = MediaFetcher.parsePicturePath(MainApplication.getInstance(), uri);
        if (!TextUtils.isEmpty(imagePath)) {
            mPickImageFile = new File(imagePath);
        }
        return mPickImageFile;
    }

    public File getTakeCameraFile() {
        return mTakeCameraFile;
    }

    public File getCropImageFile() {
        return mCropImageFile;
    }

    public File getCompressImageFile() {
        return mCompressImageFile;
    }

    public static ImageInfo parseImageInfo(File imageFile) {
        if (null != imageFile && imageFile.exists() && imageFile.isFile()) {
            ImageInfo imageInfo = new ImageInfo();
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(imageFile.getAbsolutePath(), options);
            imageInfo.mImageWidth = options.outWidth;
            imageInfo.mImageHeight = options.outHeight;
            return imageInfo;
        }
        return null;
    }

    public boolean compressImage(final File originFile, final CompressImageParam param, final ImageCompressCallback callback) {
        mCompressImageFile = null;
        if (null == originFile || !originFile.isFile() || TextUtils.isEmpty(originFile.getAbsolutePath()))
            return false;
        mCompressImageFile = generateCompressImageResultFile();
        if (null == mCompressImageFile)
            return false;

        DialogAsyncTask compressTask = new DialogAsyncTask(mActivity, null, null, false) {

            @Override
            protected Object doInBackground(Object[] objects) {
                boolean result = false;
                try {
                    // 获取转换后Bitmap
                    Bitmap resultBitmap = convertSpecifyBitmap(originFile, param);
                    Bitmap resultBitmapChecked = resultBitmap;
                    int degress = readPictureDegree(originFile.getPath());
                    AppLog.d(TAG + "image degress : " + degress);
                    if (degress > 0) { //fixme 会不会OOM?
                        resultBitmapChecked = rotateImageView(degress, resultBitmap);
                    }

                    int bitmapSize = calcBitmapMemorySize(resultBitmapChecked);
                    AppLog.d(TAG + " compressImage resultBitmap = " + (null != resultBitmapChecked ? resultBitmapChecked.getWidth() + " x " + resultBitmapChecked.getHeight() + " >> " + bitmapSize : "null"));
                    // 压缩图片流
                    OutputStream outputStream = new FileOutputStream(mCompressImageFile);
                    result = resultBitmapChecked.compress(Bitmap.CompressFormat.JPEG, 80, outputStream);
                    AppLog.d(TAG + " compressImage compress result = " + result);
                    // 释放输出流
                    try {
                        outputStream.flush();
                        outputStream.close();
                    } catch (IOException e) {
                        AppLog.w(e.getMessage());
                    }
                    // 释放ResultBitmap
                    try {
                        if (null != resultBitmapChecked && !resultBitmapChecked.isRecycled()) {
                            resultBitmapChecked.recycle();
                        }
                        if (null != resultBitmap && !resultBitmap.isRecycled()) {
                            resultBitmap.recycle();
                        }
                    } catch (Exception e) {
                        AppLog.w(e.getMessage());
                    }
                } catch (Exception e) {
                    AppLog.d(TAG + " compressImage Exception");
                } catch (Error e) {
                    AppLog.d(TAG + " compressImage Error");
                }
                AppLog.d(TAG + " compressImage result = " + result);
                return result;
            }

            @Override
            protected void onPostExecute(Object object) {
                super.onPostExecute(object);
                if (isCancelled()) {
                    if (null != callback) {
                        callback.onImageCompressCancelled();
                    }
                } else {
                    if (object != null) {
                        Boolean result = (Boolean) object;
                        if (result) {
                            if (null != callback) {
                                callback.onImageCompressSuccess(mCompressImageFile);
                            }
                        } else {
                            if (null != callback) {
                                callback.onImageCompressFailure();
                            }
                        }
                    } else {
                        if (null != callback) {
                            callback.onImageCompressFailure();
                        }
                    }
                }
            }
        };
        compressTask.execute();
        return true;
    }

    private File generateCompressImageResultFile() {
        File file = null;
        String name = "/cuitrip_compress_" + System.currentTimeMillis() + "_" + Math.random() * 9999 + ".jpg";
        try {
            String path = DictionaryUtil.getSystemPictureDir().getPath().concat(name);
            if (!TextUtils.isEmpty(path)) {
                file = new File(path);
            }
        } catch (Exception e) {
            AppLog.w(e.getMessage());
        }
        return file;
    }


    private Bitmap decodeBitmapConsiderOOM(File originFile, int requestSampleSize) throws Exception {
        AppLog.d(TAG + " decodeBitmapConsiderOOM(取样值) 开始");
        BitmapFactory.Options originOptions = new BitmapFactory.Options();
        originOptions.inJustDecodeBounds = false;
        int maxSamplePower = 4;
        int curSamplePower = 0;
        Bitmap resultBitmap = null;
        // 按照自定义比例因子进行Bitmap压缩
        if (requestSampleSize >= 1) {
            AppLog.d(TAG + " decodeBitmapConsiderOOM(取样值) 自定义比例因子压缩 开始 requestSampleSize = " + requestSampleSize);
            try {
                originOptions.inSampleSize = requestSampleSize;
                resultBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath(), originOptions);
                AppLog.d(TAG + " decodeBitmapConsiderOOM(取样值) 自定义比例因子压缩 成功");
                return resultBitmap;
            } catch (OutOfMemoryError e) {
                AppLog.d(TAG + " decodeBitmapConsiderOOM(取样值) 自定义比例因子压缩 OOM");
            } catch (Exception e) {
                AppLog.d(TAG + " decodeBitmapConsiderOOM(取样值) 自定义比例因子压缩 Exception");
            } catch (Error e) {
                AppLog.d(TAG + " decodeBitmapConsiderOOM(取样值) 自定义比例因子压缩 Error");
            }
        }
        AppLog.d(TAG + " decodeBitmapConsiderOOM(取样值) 递增比例因子压缩 开始");
        // 递增比例因子进行Bitmap压缩
        while (curSamplePower < maxSamplePower) {
            AppLog.d(TAG + " decodeBitmapConsiderOOM(取样值) 递增比例因子压缩 curSamplePower = " + curSamplePower);
            try {
                // 按照比例因子进行Bitmap压缩
                originOptions.inSampleSize = (int) Math.pow(2, curSamplePower);
                AppLog.d(TAG + " decodeBitmapConsiderOOM(取样值) 递增比例因子压缩 curSampleSize = " + originOptions.inSampleSize);
                resultBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath(), originOptions);
                AppLog.d(TAG + " decodeBitmapConsiderOOM(取样值) 递增比例因子压缩 成功");
                break;
            } catch (OutOfMemoryError e) {
                AppLog.d(TAG + " decodeBitmapConsiderOOM(取样值) 递增比例因子压缩 OOM");
                // 递增Sample因子
                curSamplePower++;
                // 如果异常,释放originBitmap
                try {
                    if (null != resultBitmap && !resultBitmap.isRecycled()) {
                        resultBitmap.recycle();
                    }
                } catch (Exception e1) {
                    AppLog.w(e1.getMessage());
                }
            } catch (Exception e) {
                AppLog.d(TAG + " decodeBitmapConsiderOOM(取样值) 递增比例因子压缩 Exception");
                throw e;
            } catch (Error e) {
                AppLog.d(TAG + " decodeBitmapConsiderOOM(取样值) 递增比例因子压缩 Error");
                throw e;
            }
        }
        return resultBitmap;
    }

    private Bitmap decodeBitmapConsiderOOM(File originFile, int requestCropWidth, int requestCropHeight, CompressImageParam.CropType requestCropType) throws Exception {
        AppLog.d(TAG + " decodeBitmapConsiderOOM(裁剪值) 开始");
        BitmapFactory.Options originOptions = new BitmapFactory.Options();
        originOptions.inJustDecodeBounds = false;
        int maxSamplePower = 4;
        int curSamplePower = 0;
        Bitmap resultBitmap = null;
        // 递增比例因子进行Bitmap压缩
        while (curSamplePower < maxSamplePower) {
            AppLog.d(TAG + " decodeBitmapConsiderOOM(裁剪值) 递增比例因子压缩 curSamplePower = " + curSamplePower);
            try {
                // 按照比例因子进行Bitmap压缩
                originOptions.inSampleSize = (int) Math.pow(2, curSamplePower);
                AppLog.d(TAG + " decodeBitmapConsiderOOM(裁剪值) 递增比例因子压缩 curSampleSize = " + originOptions.inSampleSize);
                Bitmap originBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath(), originOptions);
                AppLog.d(TAG + " decodeBitmapConsiderOOM(裁剪值) 递增比例因子压缩 成功");
                int bitmapWidth = originBitmap.getWidth();
                int bitmapHeight = originBitmap.getHeight();
                // 如果需求长宽与原图长宽一致或大于,则直接返回原图
                if (requestCropWidth >= bitmapWidth) {
                    requestCropWidth = bitmapWidth;
                }
                if (requestCropHeight >= bitmapHeight) {
                    requestCropHeight = bitmapHeight;
                }
                AppLog.d(TAG + " decodeBitmapConsiderOOM(裁剪值) bitmapWidth,bitmapHeight,requestCropWidth,requestCropHeight,requestCropType = " + bitmapWidth + "," + bitmapHeight + "," + requestCropWidth + "," + requestCropHeight + "," + requestCropType);
                int X = (bitmapWidth - requestCropWidth) / 2;
                int Y = (bitmapHeight - requestCropHeight) / 2;
                if (null != requestCropType) {
                    switch (requestCropType) {
                        case LEFT_TOP:
                            X = 0;
                            Y = 0;
                            break;
                        case LEFT_BOTTOM:
                            X = 0;
                            Y = bitmapHeight - requestCropHeight;
                            break;
                        case RIGHT_BOTTOM:
                            X = bitmapWidth - requestCropWidth;
                            Y = bitmapHeight - requestCropHeight;
                            break;
                        case RIGHT_TOP:
                            X = bitmapWidth - requestCropWidth;
                            Y = 0;
                            break;
                        case CENTER:
                            X = (bitmapWidth - requestCropWidth) / 2;
                            Y = (bitmapHeight - requestCropHeight) / 2;
                            break;
                    }
                }
                resultBitmap = Bitmap.createBitmap(originBitmap, X, Y, requestCropWidth, requestCropHeight, null, false);
                break;
            } catch (OutOfMemoryError e) {
                AppLog.d(TAG + " decodeBitmapConsiderOOM(裁剪值) 递增比例因子压缩 OOM");
                // 递增Sample因子
                curSamplePower++;
                // 如果异常,释放originBitmap
                try {
                    if (null != resultBitmap && !resultBitmap.isRecycled()) {
                        resultBitmap.recycle();
                    }
                } catch (Exception e1) {
                    AppLog.w(e1.getMessage());
                }
            } catch (Exception e) {
                AppLog.d(TAG + " decodeBitmapConsiderOOM(裁剪值) 递增比例因子压缩 Exception");
                throw e;
            } catch (Error e) {
                AppLog.d(TAG + " decodeBitmapConsiderOOM(裁剪值) 递增比例因子压缩 Error");
                throw e;
            }
        }
        return resultBitmap;
    }

    private Bitmap decodeBitmapConsiderOOM(File originFile, int requestCompressSize, CompressImageParam.CompressSizeType requestCompressSizeType) throws Exception {
        AppLog.d(TAG + " decodeBitmapConsiderOOM(压缩值) 开始");
        BitmapFactory.Options originOptions = new BitmapFactory.Options();
        originOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(originFile.getAbsolutePath(), originOptions);
        int originBitmapWidth = originOptions.outWidth;
        int originBitmapHeight = originOptions.outHeight;
        int originSampleSize = 1;
        if (requestCompressSize >= originBitmapWidth && requestCompressSize >= originBitmapHeight) {
            requestCompressSize = Math.max(originBitmapWidth, originBitmapHeight);
        }
        if (null == requestCompressSizeType)
            requestCompressSizeType = CompressImageParam.CompressSizeType.LARGER_SIZE;
        if (null != requestCompressSizeType) {
            switch (requestCompressSizeType) {
                case SMALLER_SIZE:
                    if (requestCompressSize < originBitmapWidth && requestCompressSize < originBitmapHeight) {
                        originSampleSize = Math.round((float) Math.max(originBitmapWidth, originBitmapHeight) / requestCompressSize);
                    } else {
                        originSampleSize = Math.round((float) Math.max(originBitmapWidth, originBitmapHeight) / requestCompressSize);
                    }
                    break;
                case LARGER_SIZE:
                    if (requestCompressSize < originBitmapWidth && requestCompressSize < originBitmapHeight) {
                        originSampleSize = Math.round((float) Math.min(originBitmapWidth, originBitmapHeight) / requestCompressSize);
                    } else {
                        originSampleSize = Math.round((float) Math.max(originBitmapWidth, originBitmapHeight) / requestCompressSize);
                    }
                    break;
            }
        }
        originOptions.inJustDecodeBounds = false;
        AppLog.d(TAG + " decodeBitmapConsiderOOM(压缩值) originBitmapWidth,originBitmapHeight,requestCompressSize,requestCompressSizeType,originSampleSize = " + originBitmapWidth + "," + originBitmapHeight + "," + requestCompressSize + "," + requestCompressSizeType + "," + originSampleSize);
        int maxSamplePower = 4;
        int curSamplePower = 0;
        Bitmap resultBitmap = null;
        // 递增比例因子进行Bitmap压缩
        while (curSamplePower < maxSamplePower) {
            AppLog.d(TAG + " decodeBitmapConsiderOOM(压缩值) 递增比例因子压缩 curSamplePower = " + curSamplePower);
            try {
                // 按照比例因子进行Bitmap压缩
                originOptions.inSampleSize = (int) Math.pow(2, curSamplePower) * originSampleSize;
                AppLog.d(TAG + " decodeBitmapConsiderOOM(压缩值) 递增比例因子压缩 curSampleSize = " + originOptions.inSampleSize);
                resultBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath(), originOptions);
                AppLog.d(TAG + " decodeBitmapConsiderOOM(压缩值) 递增比例因子压缩 成功");
                break;
            } catch (OutOfMemoryError e) {
                AppLog.d(TAG + " decodeBitmapConsiderOOM(压缩值) 递增比例因子压缩 OOM");
                // 递增Sample因子
                curSamplePower++;
                // 如果异常,释放originBitmap
                try {
                    if (null != resultBitmap && !resultBitmap.isRecycled()) {
                        resultBitmap.recycle();
                    }
                } catch (Exception e1) {
                    AppLog.w(e1.getMessage());
                }
            } catch (Exception e) {
                AppLog.d(TAG + " decodeBitmapConsiderOOM(压缩值) 递增比例因子压缩 Exception");
                throw e;
            } catch (Error e) {
                AppLog.d(TAG + " decodeBitmapConsiderOOM(压缩值) 递增比例因子压缩 Error");
                throw e;
            }
        }
        return resultBitmap;
    }

    /**
     * 旋转bitmap
     * @param angle
     * @param bitmap
     * @return
     */
    public static Bitmap rotateImageView(int angle, Bitmap bitmap) {
        //旋转图片 动作
        Matrix matrix = new Matrix();;
        matrix.postRotate(angle);
        // 创建新的图片
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
                bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        return resizedBitmap;
    }

    /**
     * 读取图片旋转的角度
     * @param path
     * @return
     */
    public static int readPictureDegree(String path) {
        int degree  = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

    private Bitmap convertSpecifyBitmap(File originFile, CompressImageParam param) throws Exception, Error {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(originFile.getAbsolutePath(), options);
        int bitmapWidth = options.outWidth;
        int bitmapHeight = options.outHeight;
        Bitmap.Config bitmapConfig = options.inPreferredConfig;
        int bitmapSize = calcImageFileSize(originFile);
        AppLog.d(TAG + " convertSpecifyBitmap bitmapWidth,bitmapHeight,bitmapSize,bitmapConfig = " + bitmapWidth + "," + bitmapHeight + "," + bitmapSize + "," + bitmapConfig);
        // 计算压缩参数值
        int requestCompressSampleSize = 1;
        int requestCompressSize = 0;
        CompressImageParam.CompressSizeType requestCompressSizeType = null;
        int requestCropWidth = 0;
        int requestCropHeight = 0;
        CompressImageParam.CropType requestCropType = null;
        if (null != param) {
            if (param.mCompressSampleSize > 0) {
                requestCompressSampleSize = param.mCompressSampleSize;
            }
            if (param.mCompressSize > 0) {
                requestCompressSize = param.mCompressSize;
            }
            requestCompressSizeType = param.mCompressSizeType;
            if (param.mCropWidth > 0) {
                requestCropWidth = param.mCropWidth;
            }
            if (param.mCropHeight > 0) {
                requestCropHeight = param.mCropHeight;
            }
            requestCropType = param.mCropType;
        }
        AppLog.d(TAG + " convertSpecifyBitmap requestCompressSampleSize,requestCompressSize,requestCompressSizeType,requestCropWidth,requestCropHeight,requestCropType = " + requestCompressSampleSize + " >> " + requestCompressSize + "," + requestCompressSizeType + " >> " + requestCropWidth + " x " + requestCropHeight + "," + requestCropType);
        // 根据压缩值进行Bitmap转换
        if (requestCompressSize > 0) {
            AppLog.d(TAG + " convertSpecifyBitmap (压缩值Bitmap转换) 开始");
            Bitmap resultBitmap = decodeBitmapConsiderOOM(originFile, requestCompressSize, requestCompressSizeType);
            AppLog.d(TAG + " convertSpecifyBitmap(压缩值Bitmap转换) 成功");
            return resultBitmap;
        }
        // 根据裁剪值进行Bitmap转换
        else if (requestCropWidth > 0 && requestCropHeight > 0) {
            AppLog.d(TAG + " convertSpecifyBitmap (裁剪值Bitmap转换) 开始");
            Bitmap resultBitmap = decodeBitmapConsiderOOM(originFile, requestCropWidth, requestCropHeight, requestCropType);
            AppLog.d(TAG + " convertSpecifyBitmap (裁剪值Bitmap转换) 成功");
            return resultBitmap;
        }
        // 根据取样值进行Bitmap转换
        else {
            AppLog.d(TAG + " convertSpecifyBitmap (取样值Bitmap转换) 开始");
            Bitmap resultBitmap = decodeBitmapConsiderOOM(originFile, requestCompressSampleSize);
            AppLog.d(TAG + " convertSpecifyBitmap (取样值Bitmap转换) 成功");
            return resultBitmap;
        }
    }

    private boolean checkEnvironment() {
        if (mOpenMode == OPEN_MODE_ACTIVITY) {
            if (null != mActivity) {
                return true;
            }
        } else if (mOpenMode == OPEN_MODE_FRAGMENT) {
            if (null != mActivity && null != mFragment) {
                return true;
            }
        }
        return false;
    }

    public interface ImageCompressCallback {
        void onImageCompressSuccess(File resultFile);

        void onImageCompressFailure();

        void onImageCompressCancelled();
    }

    public static class CropImageParam {

        public CropImageParam(int aspectX, int aspectY, int outputX, int outputY) {
            mAspectX = aspectX;
            mAspectY = aspectY;
            mOutputX = outputX;
            mOutputY = outputY;
        }

        public int mAspectX;
        public int mAspectY;
        public int mOutputX;
        public int mOutputY;

    }

    public static class CompressImageParam {

        public CompressImageParam(int compressSampleSize) {
            mCompressSampleSize = compressSampleSize;
        }

        public CompressImageParam(int compressSize, CompressSizeType compressSizeType) {
            mCompressSize = compressSize;
            mCompressSizeType = compressSizeType;
        }

        public CompressImageParam(int cropWidth, int cropHeight, CropType cropType) {
            mCropWidth = cropWidth;
            mCropHeight = cropHeight;
            mCropType = cropType;
        }

        public int mCompressSampleSize;

        public int mCompressSize;
        public CompressSizeType mCompressSizeType;

        public int mCropWidth;
        public int mCropHeight;
        public CropType mCropType;

        public static enum CompressSizeType {
            SMALLER_SIZE, LARGER_SIZE;
        }

        public static enum CropType {
            LEFT_TOP, LEFT_BOTTOM, RIGHT_BOTTOM, RIGHT_TOP, CENTER;
        }

    }

    public static class ImageInfo {
        public int mImageWidth;
        public int mImageHeight;
    }

    public enum Source {
        SELF_INFO_SELECT,
        CREATE_SERVICE,
        SELF_HOME_PAGE_EDITOR
        ;
    }

    public static int calcBitmapMemorySize(Bitmap bitmap) {
        int size = 0;
        if (null != bitmap) {
            size = bitmap.getRowBytes() * bitmap.getHeight();
        }
        return size;
    }

    public static int calcImageFileSize(File imageFile) {
        int size = 0;
        if (null != imageFile && imageFile.isFile() && imageFile.exists()) {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(imageFile.getAbsolutePath(), options);
            int width = options.outWidth;
            int height = options.outHeight;
            Bitmap.Config config = options.inPreferredConfig;
            if (null != config) {
                switch (config) {
                    case ALPHA_8:
                        size = width * height * 1;
                        break;
                    case RGB_565:
                        size = width * height * 2;
                        break;
                    case ARGB_4444:
                        size = width * height * 2;
                        break;
                    case ARGB_8888:
                        size = width * height * 4;
                        break;
                }
            }
        }
        return size;
    }

}
